using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Comteck.Dto.Sys;
using Comteck.Localization;
using Comteck.Winforms.Data;
using Comteck.Winforms.Utils;
using DevExpress.XtraBars;
using DevExpress.XtraTab;

namespace Comteck.Winforms.Forms {
  /// <summary>
  /// 窗口基类
  /// </summary>
  public partial class FrmBase : FrmSkinBase {
    protected internal int InitHashCode;

    #region fields

    #region 是否启用 按Escape关闭窗口

    /// <summary>
    /// 是否启用 按Escape关闭窗口
    /// </summary>
    [EditorBrowsable(EditorBrowsableState.Always)]
    [Category("扩展属性"), Description("是否启用 按Escape关闭窗口")]
    [Browsable(true), DefaultValue(true)]
    public bool EnableCloseByEscape { get; set; } = false;

    /// <summary>
    /// 是否启用 回车键代替tab键,适用于表单录入
    /// </summary>
    [EditorBrowsable(EditorBrowsableState.Always)]
    [Category("扩展属性"), Description("是否启用 回车键代替tab键,适用于表单录入")]
    [Browsable(true), DefaultValue(false)]
    public bool EnableEnter2Tab { get; set; } = false;

    /// <summary>
    /// 隐藏底部
    /// </summary>
    public bool HiddenBaseBottom { get; set; } = false;

    #endregion

    #region 主键

    /// <summary>
    /// 控件的前缀,默认为 ck
    /// </summary>
    [Browsable(false)]
    protected const string ControlPrefix = "ck";

    /// <summary>
    /// 主键(主要在编辑用) add by weijie.sun 2013/10/12
    /// </summary>
    [Browsable(false)]
    public virtual object EntityId { get; set; }

    #endregion

    #region 权限相关

    /// <summary>
    /// 权限文本描述内容
    /// </summary>
    private string fullAuthTextFormat = string.Empty;

    /// <summary>
    /// frmbase load之前的事件
    /// </summary>
    /// <param name="frmBase"></param>
    public delegate void FrmBaseBeforeLoadHandle();

    #endregion

    /// <summary>
    /// 当在action界面新增或者修改记录后，刷新主界面列表信息
    /// </summary>
    [Browsable(false)]
    public Action<object> AddOrUpdateAction { get; set; }
    /// <summary>
    /// 当在action界面新增或者修改记录后，刷新主界面列表信息
    /// </summary>
    [Browsable(false)]
    public Action<object> AddOrUpdateBulkAction { get; set; }

    /// <summary>
    /// bool返回值
    /// </summary>
    /// <param name="data"></param>
    [Browsable(false)]
    public delegate bool BoolAction<in T>(T data);

    /// <summary>
    /// bool返回值
    /// </summary>
    /// <param name="data"></param>
    [Browsable(false)]
    public delegate Task<bool> BoolActionAsync<in T>(T data);

    /// <summary>
    /// 锁
    /// </summary>
    protected object LockObj = new object();

    /// <summary>
    /// 
    /// </summary>
    protected MenuAuthDto MenuAuth { get; set; }

    /// <summary>
    /// 
    /// </summary>
    [Browsable(false)]
    public bool AutoSearchOnFormLoad = false;

    #endregion

    #region Ctor

    /// <summary>
    /// 
    /// </summary>
    public FrmBase() {
      InitializeComponent();
      ////设定按字体来缩放控件
      //this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      ////设定字体大小为12px     
      //this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel, ((byte)(134)));

      this.Initialize();
    }

    private void Initialize() {
      // 此处不能根据 DesignMode 来判断是否处于设计器模式，必须使用以下语句判断
      if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime) {
        return;
      } else if (System.Diagnostics.Process.GetCurrentProcess().ProcessName.ToLower() == "devenv") {
        return;
      }

      // 当前表单
      this.MenuAuth = this.FindMenuAuth();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    protected MenuAuthDto FindMenuAuth() {
      // 程序集和名称
      var assemblyName = this.GetType().Assembly.GetName().Name;
      var formPath = this.GetType().FullName;

      return SysGlobal.MenuList
        .Where(x => x.Form_Assembly_Name.IsNotNullOrEmpty() && x.Form_Path.IsNotNullOrEmpty())
        .Where(x => x.Form_Assembly_Name.ToLower() == assemblyName.ToLower() && x.Form_Path.ToLower() == formPath.ToLower())
        .OrderBy(x => x.Id)
        .FirstOrDefault();
    }

    #endregion

    #region 窗口加载

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void FrmBase_Load(object sender, EventArgs e) {
      if (this.DesignMode) {
        return;
      }

      // status form name
      barStatusForm.Caption = this.Name;

      //// 显示窗口名
      //if (LocalDbData.Local_Db_Info.ShowFormName != 1) {
      //  this.barBaseBottom.Visible = false;
      //}

      // 隐藏底部
      if (this.HiddenBaseBottom) {
        this.barBaseBottom.Visible = false;
      }

      // 接受事件
      if (this.EnableEnter2Tab == true) {
        this.KeyPreview = true;
      }
    }

    #endregion

    #region 表达赋值

    /// <summary>
    /// 将表单上的值填充到实体类中
    /// </summary>
    /// <typeparam name="T">实体类类型</typeparam>
    /// <param name="container">System.Windows.Forms.Control,控件所在的容器</param>
    /// <param name="model">实体类值</param>
    /// <param name="prefix">表单控件中的前缀,比如ck_</param>
    /// <returns></returns>
    public virtual T FillForm2Model<T>(Control container, T model = null, string prefix = ControlPrefix)
      where T : class, new() {
      return WinformHelper.FillForm2Model<T>(container, model, prefix);
    }

    /// <summary>
    /// 把实体类的值填充到表单中去(仅限于服务器控件)
    /// </summary>
    /// <typeparam name="T">实体类</typeparam>
    /// <param name="container">System.Web.UI.Control,控件所在的容器</param>
    /// <param name="t">实例化</param>
    /// <param name="prefix">表单中的前缀,比如 kj_UserID</param>
    public virtual void FillModel2Form<T>(Control container, T t, string prefix = ControlPrefix) {
      WinformHelper.FillModel2Form<T>(container, t, prefix);
    }

    #endregion

    #region 通用打印

    /// <summary>
    /// 打开通用打印对话框(支持单字段)
    /// </summary>
    /// <param name="printList">待打印的数据集合：int或string的泛型</param>
    /// <param name="idirectPrintd">是否直接打印</param>
    /// <para>如果只有一条记录，则直接打印预览，否则就打开对话框</para>
    /// </summary>
    protected async Task<bool> OpenPrintDialog(List<dynamic> printList, bool directPrint = false) {
      ajaxLoad.Show();
      var result = await LocalDbDataHelper.OpenPrintDialog(this.MenuAuth?.Id, printList, directPrint);
      ajaxLoad.Hide();
      return result;
    }

    ///// <summary>
    ///// </summary>
    ///// 打开通用打印对话框(支持多字段)
    ///// <param name="printList">待打印的Zd_Temp_Table数据集合</par
    ///// <param name="formId">不传值时用当前窗体，否则用指定的窗体</param>
    ///// <para>如果只有一条记录，则直接打印预览，否则就打开对话框</para>
    ///// </summary>
    //protected async void OpenPrintDialogEx(List<Zd_Temp_Table> printList, string id = null) {
    //  ajaxLoad.Show();
    //  await LocalDbDataHelper.OpenPrintDialogEx(id ?? this.Zd_Form?.Id, printList);
    //  ajaxLoad.Hide();
    //}

    #endregion

    #region 复制窗口名到粘贴板

    /// <summary>
    /// 窗体名双击事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void barStatusForm_ItemDoubleClick(object sender, ItemClickEventArgs e) {
      // 复制窗口名到粘贴板
      try {
        Clipboard.SetText(this.barStatusForm.Caption);
      } catch (Exception ex) {
        Logger.Error($"复制窗口名到粘贴板出错,{ex.Message}");
      }
    }

    #endregion

    #region FormClosing

    /// <summary>
    /// 
    /// </summary>
    /// <param name="e"></param>
    protected override void OnFormClosing(FormClosingEventArgs e) {
      if (e.CloseReason == CloseReason.UserClosing) {
        base.OnFormClosing(e);
      }
    }

    #endregion

    #region 是否显示进度条

    /// <summary>
    /// 
    /// </summary>
    /// <param name="show"></param>
    protected void ShowProgressStatus(bool show = true) {
      barProgressStatus.Visibility = show ? BarItemVisibility.Always : BarItemVisibility.Never;
      barProgressStop.Visibility = show ? BarItemVisibility.Always : BarItemVisibility.Never;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="maximum"></param>
    protected void SetProgressMax(int maximum) {
      repositoryItemProgressBar2.Maximum = maximum;
      barProgressStatus.EditValue = 0;
      barProgressStop.Visibility = BarItemVisibility.Always;
    }

    /// <summary>
    /// 进度条自增1
    /// </summary>
    /// <param name="maximum"></param>
    protected virtual void SetProgressIncrease() {
      SysGlobal.SynchronizationContext.Send((m) => {
        barProgressStatus.EditValue = barProgressStatus.EditValue.To<int>() + 1;
      }, null);
    }

    /// <summary>
    /// 进度条达到最大
    /// </summary>
    /// <param name="maximum"></param>
    protected void SetProgressIncreaseMax() {
      SysGlobal.SynchronizationContext.Send((m) => {
        barProgressStatus.EditValue = repositoryItemProgressBar2.Maximum;
      }, null);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void barProgressStop_ItemClick(object sender, ItemClickEventArgs e) {
      // 已经停止
      if (ajaxLoad == null || ajaxLoad.IsWork() == false) {
        return;
      }

      var dialog = this.ShowMsg("您确定要停止查询吗？", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);

      if (dialog == DialogResult.No) {
        return;
      }

      // 停止
      ajaxLoad?.Hide();

      // 
      barProgressStop.Visibility = BarItemVisibility.Never;
    }

    #endregion

    #region 加载与关闭窗口  add by geping@2021-05-01
    /// <summary>
    /// XtraTabControl 实现动态加载窗口功能
    /// </summary>
    /// <param name="tabControl"></param>
    /// <param name="tabPage"></param>
    /// <param name="form"></param>
    /// <param name="isDataModify">界面上的数据是否有过编辑：true=是，false=否</param>
    /// <param name="isNewOrder">是否新单：True=是（默认值），False=否</param>
    protected internal void LoadForm(XtraTabControl tabControl, XtraTabPage tabPage, FrmBase form, bool isDataModify, bool isNewOrder = true) {
      form.TopLevel = false;
      form.Dock = DockStyle.Fill;
      form.FormBorderStyle = FormBorderStyle.None;
      form.WindowState = FormWindowState.Normal; // 此处必须设置为默认，否则界面打开空白
#if !DEBUG                            
      form.barBaseBottom.Visible = false;
#endif

      if (isNewOrder) {
        if (tabControl.TabPages.Any(x => x.Name == tabPage.Name)) {
          var page = tabControl.TabPages.First(x => x.Name == tabPage.Name);

          if (page.Controls.OfType<FrmBase>().Any()) {
            if (isDataModify && this.ShowMsg(
              MarketResources.Save_After_Edit_Msg,
              MarketResources.TipTitle,
              MessageBoxButtons.YesNo,
              MessageBoxIcon.Information,
              MessageBoxDefaultButton.Button1) == DialogResult.Yes) {
              tabControl.SelectedTabPage = page;
              return;
            }

            tabControl.TabPages.Remove(page);
            LoadNewForm(tabControl, tabPage, form);
          }
        } else {
          LoadNewForm(tabControl, tabPage, form);
        }
      } else {
        if (tabControl.TabPages.Any(x => x.Name == tabPage.Name)) {
          tabControl.SelectedTabPage = tabControl.TabPages.First(x => x.Name == tabPage.Name);
        } else {
          LoadNewForm(tabControl, tabPage, form);
        }
      }
    }

    private static void LoadNewForm(XtraTabControl tabControl, XtraTabPage tabPage, Control form) {
      tabPage.Controls.Add(form);
      tabControl.TabPages.Add(tabPage);
      form.Show();

      tabControl.SelectedTabPage = tabPage;
    }

    /// <summary>
    /// 在编辑界面打开新单界面
    /// </summary>
    /// <param name="oldForm"></param>
    /// <param name="newForm"></param>
    /// <param name="isDataModify"></param>
    protected internal void LoadForm(FrmBase oldForm, FrmBase newForm, bool isDataModify) {
      if (oldForm.Parent is XtraTabPage tabPage && tabPage.Parent is XtraTabControl tabControl) {
        newForm.Owner = this.Owner;
        newForm.AddOrUpdateAction = this.AddOrUpdateAction;

        this.LoadForm(tabControl, new XtraTabPage {
          Name = "tpNew",
          Text = @"新单据",
        }, newForm, isDataModify);
      }
    }

    /// <summary>
    /// 关闭动态加载界面
    /// </summary>
    /// <param name="form"></param>
    /// <param name="isDataModify"></param>
    protected internal void CloseForm(FrmBase form, bool isDataModify) {
      if (isDataModify && this.ShowMsg(
        MarketResources.Save_After_Edit_Msg,
        MarketResources.TipTitle,
        MessageBoxButtons.YesNo,
        MessageBoxIcon.Information,
        MessageBoxDefaultButton.Button1) == DialogResult.Yes) {
        return;
      }

      if (form.Parent is XtraTabPage tabPage && tabPage.Parent is XtraTabControl tabControl){
        tabControl.TabPages.Remove(tabPage);
      } else {
        form.Close();
      }
    }
    /// <summary>
    /// 在管理界面关闭所有界面
    /// </summary>
    /// <param name="form"></param>
    /// <param name="tabControl"></param>
    protected internal void CloseAllForm(FrmBase form, XtraTabControl tabControl) {
      for (var i = tabControl.TabPages.Count - 1; i >= 0; i--) {
        var tabPage = tabControl.TabPages[i];

        if (!tabPage.Controls.OfType<FrmBase>().Any()) { continue; }

        tabControl.SelectedTabPage = tabPage;

        var frm = tabPage.Controls.OfType<FrmBase>().First();
        var curType = frm.GetType();
        var methodInfo = curType.GetMethod("GetHashCode");
        var hashCode = methodInfo?.Invoke(frm, null);

        if (frm.InitHashCode != hashCode.To<int?>()
          && this.ShowMsg(
            MarketResources.Save_After_Edit_Msg,
            MarketResources.TipTitle,
            MessageBoxButtons.YesNo,
            MessageBoxIcon.Information,
            MessageBoxDefaultButton.Button1) == DialogResult.Yes) {
          return;
        }

        tabControl.TabPages.Remove(tabPage);
      }

      form.Close();
    }
    #endregion
  }
}
